Gatsbyは静的サイトだけじゃない。Gatsby Funcstionsで問い合わせフォームを作ってみた。

Gatsbyは静的サイトだけじゃない。Gatsby Funcstionsで問い合わせフォームを作ってみた。

Clock Icon2022.02.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも、ベルリンオフィスの小西です。

静的サイト生成フレームワークであるGatsbyでは、しばらく前に Functions という動的なアプリが構築できる機能がリリースされています。ユーザー認証や外部APIへのリクエスト、サードパーティサービスとの連携などが可能になります。

先日、そのGatsby Functionsを使ってお問い合わせフォームを作ることがあったので、備忘録としてまとめておきます。

1. Gatsby立ち上げ

ローカルでGatsbyをインストールしてサンプルアプリを立ち上げます。

% npm install -g gatsby-cli
% gatsby new hello-world
% cd hello-world
% gatsby develop

http://localhost:8000/ にアクセスするとGatsbyのスターターサイトが立ち上がるはずです。今回はこれをベースに問い合わせフォームを実装してみます。

2. 必要なパッケージインストール

Gatsbyアプリからのメール送信用に Nodemailer を使います。

% npm install nodemailer

3. APIの作成

今回私はSMTPとしてSendgridを使いますが、Sendgridのセットアップは省略します。

まず、src ディレクトリ直下に api ディレクトリがない場合は作成します。

その中に form.js ファイルを作ります。ソースコードは下記です。

ご自身のSMTPに合わせて、 port , host , user , pass は適切な値にしてください。

export default function formHandler(req, res) {

  let nodemailer = require('nodemailer')
  const transporter = nodemailer.createTransport({
    port: 465,
    host: 'smtp.sendgrid.net',
    auth: {
      user: 'apikey',
      pass: 'PASSWORD',
    },
    secure: true,
  })

  if (!req.body.email) {
    return res.status(422).json("Email is required")
  }

  const mailData = {
    from: 'TEST Sender <mail@example.com>',
    to: req.body.email ? req.body.email : '',
    subject: 'Thanks for the inquiry!',
    html: req.body.emailBody ? `<p>${req.body.emailBody}</p>` : "Null message.",
  }

  const results = transporter.sendMail(mailData)
    .then(result => res.status(200).json(JSON.stringify(result)))
    .catch(error => res.status(500).json(JSON.stringify(error)))
}

やっていること

  • ユーザーの入力した情報を元に自動返信メールを生成する(送信先=入力された `email` , 本文 = 入力された `emailBody` )
    • `email` 欄の入力がなければエラーで返す
  • SendgridのSMTPを使ってメールを送信を行い、成功したら200、エラーであれば500で返す

4. 問い合わせページの作成

次に、先ほどのAPIを呼び出すページを作成します。

ユーザーに、自分のEメールとメッセージのみを入力してもらうシンプルな入力フォームです。

import * as React from "react"
import Layout from "../components/layout"
import Seo from "../components/seo"

export default function FormPage() {
  const [value, setValue] = React.useState({})
  const [serverResponse, setServerResponse] = React.useState('')

  function handleChange(e) {
    value[e.target.id] = e.target.value
    setServerResponse('')
    setValue({ ...value })
  }

  async function onSubmit(e) {
    e.preventDefault()
    const response = await window
      .fetch('/api/form', {
        method: 'POST',
        headers: {
          "content-type": "application/json",
        },
        body: JSON.stringify(value),
      })
      .then(res => res.json())
    setServerResponse(response)
  }

  return (
  <Layout>
    <Seo title="Sample Contact Form" />
    <h1>Sample Form Page</h1>
    <div>
      <h2>Server response</h2>
      <p>{serverResponse}</p>
    </div>
    <hr />
    <form onSubmit={onSubmit} method="POST" action="/api/form" className="formWrapper">
      <h2>Contact Form</h2>
      <div className="formBlock">
        <label>
          <span>Email</span>
          <input
            type="email"
            name="email"
            id="email"
            value={value['email'] || ``}
            onChange={handleChange} />
        </label>
      </div>
      <div className="formBlock">
        <label>
          <span>Subject</span>
          <textarea
            name="emailBody"
            id="emailBody"
            value={value['emailBody'] || ''}
            onChange={handleChange} />
        </label>
      </div>
      <div className="formBlock">
        <input type="submit" />
      </div>
      <div className="formBlock">
        <input type="reset" value="Clear" />
      </div>
    </form>
  </Layout>
)}

これで構築は完了しましたので、実際に触ってみます。

5. 実際に動かしてみる

http://localhost:8000/form/ をブラウザで開きます。

gatsby

※「4. 問い合わせページの作成」で作ったページに別途CSSをあてています。

自分のメールアドレスと適当なメッセージを入力し、「Submit」を押します。 gatsby

Server Responseが無事返ってくれば成功です。

さらに、入力したメールアドレス宛に自動返信メールも届いているはずです。

さいごに

簡単にではありますが、Gatsby Functionsを試してみました。

Netlifyなどは静的サイトに組み込めるフォーム機能をホストマシン側で提供していましたが、これでGatsby単体で動的な機能の実装もできるようになりました。

いよいよシンプルな構成のサイトはGatsbyだけでOKという感じになってきて個人的に嬉しい限りです。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.